/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controladoresJpa;

import controladoresJpa.exceptions.IllegalOrphanException;
import controladoresJpa.exceptions.NonexistentEntityException;
import controladoresJpa.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import model.Esquema;
import model.Projetista;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Persistence;
import model.DicionarioMER;
import model.DicionarioMR;

/**
 * Módulo Gerência
 * Classe de Entidade do Banco de Dados, gerada automaticamente, porém com certas modificações
 * @author Eduardo, Maylon e Kamilla
 */
public class EsquemaJpaController implements Serializable {

    public EsquemaJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;
public EsquemaJpaController(){
    if(emf==null)
        emf = Persistence.createEntityManagerFactory("unb-gama-threedsPU");
            }
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Esquema esquema) throws PreexistingEntityException, Exception {
        if (esquema.getProjetistaList() == null) {
            esquema.setProjetistaList(new ArrayList<Projetista>());
        }
        if (esquema.getDicionarioMERList() == null) {
            esquema.setDicionarioMERList(new ArrayList<DicionarioMER>());
        }
        if (esquema.getDicionarioMRList() == null) {
            esquema.setDicionarioMRList(new ArrayList<DicionarioMR>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            List<Projetista> attachedProjetistaList = new ArrayList<Projetista>();
            for (Projetista projetistaListProjetistaToAttach : esquema.getProjetistaList()) {
                projetistaListProjetistaToAttach = em.getReference(projetistaListProjetistaToAttach.getClass(), projetistaListProjetistaToAttach.getEMail());
                attachedProjetistaList.add(projetistaListProjetistaToAttach);
            }
            esquema.setProjetistaList(attachedProjetistaList);
            List<DicionarioMER> attachedDicionarioMERList = new ArrayList<DicionarioMER>();
            for (DicionarioMER dicionarioMERListDicionarioMERToAttach : esquema.getDicionarioMERList()) {
                dicionarioMERListDicionarioMERToAttach = em.getReference(dicionarioMERListDicionarioMERToAttach.getClass(), dicionarioMERListDicionarioMERToAttach.getId());
                attachedDicionarioMERList.add(dicionarioMERListDicionarioMERToAttach);
            }
            esquema.setDicionarioMERList(attachedDicionarioMERList);
            List<DicionarioMR> attachedDicionarioMRList = new ArrayList<DicionarioMR>();
            for (DicionarioMR dicionarioMRListDicionarioMRToAttach : esquema.getDicionarioMRList()) {
                dicionarioMRListDicionarioMRToAttach = em.getReference(dicionarioMRListDicionarioMRToAttach.getClass(), dicionarioMRListDicionarioMRToAttach.getId());
                attachedDicionarioMRList.add(dicionarioMRListDicionarioMRToAttach);
            }
            esquema.setDicionarioMRList(attachedDicionarioMRList);
            em.persist(esquema);
            for (Projetista projetistaListProjetista : esquema.getProjetistaList()) {
                projetistaListProjetista.getEsquemaList().add(esquema);
                projetistaListProjetista = em.merge(projetistaListProjetista);
            }
            for (DicionarioMER dicionarioMERListDicionarioMER : esquema.getDicionarioMERList()) {
                Esquema oldNomeProjetoOfDicionarioMERListDicionarioMER = dicionarioMERListDicionarioMER.getNomeEsquema();
                dicionarioMERListDicionarioMER.setNomeEsquema(esquema);
                dicionarioMERListDicionarioMER = em.merge(dicionarioMERListDicionarioMER);
                if (oldNomeProjetoOfDicionarioMERListDicionarioMER != null) {
                    oldNomeProjetoOfDicionarioMERListDicionarioMER.getDicionarioMERList().remove(dicionarioMERListDicionarioMER);
                    oldNomeProjetoOfDicionarioMERListDicionarioMER = em.merge(oldNomeProjetoOfDicionarioMERListDicionarioMER);
                }
            }
            for (DicionarioMR dicionarioMRListDicionarioMR : esquema.getDicionarioMRList()) {
                Esquema oldNomeProjetoOfDicionarioMRListDicionarioMR = dicionarioMRListDicionarioMR.getNomeEsquema();
                dicionarioMRListDicionarioMR.setNomeEsquema(esquema);
                dicionarioMRListDicionarioMR = em.merge(dicionarioMRListDicionarioMR);
                if (oldNomeProjetoOfDicionarioMRListDicionarioMR != null) {
                    oldNomeProjetoOfDicionarioMRListDicionarioMR.getDicionarioMRList().remove(dicionarioMRListDicionarioMR);
                    oldNomeProjetoOfDicionarioMRListDicionarioMR = em.merge(oldNomeProjetoOfDicionarioMRListDicionarioMR);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findEsquema(esquema.getNome()) != null) {
                throw new PreexistingEntityException("Esquema " + esquema + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Esquema esquema) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Esquema persistentEsquema = em.find(Esquema.class, esquema.getNome());
            List<Projetista> projetistaListOld = persistentEsquema.getProjetistaList();
            List<Projetista> projetistaListNew = esquema.getProjetistaList();
            List<DicionarioMER> dicionarioMERListOld = persistentEsquema.getDicionarioMERList();
            List<DicionarioMER> dicionarioMERListNew = esquema.getDicionarioMERList();
            List<DicionarioMR> dicionarioMRListOld = persistentEsquema.getDicionarioMRList();
            List<DicionarioMR> dicionarioMRListNew = esquema.getDicionarioMRList();
            List<String> illegalOrphanMessages = null;
            
            if( dicionarioMERListNew !=null)
            for (DicionarioMER dicionarioMERListOldDicionarioMER : dicionarioMERListOld) {
                if (!dicionarioMERListNew.contains(dicionarioMERListOldDicionarioMER)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain DicionarioMER " + dicionarioMERListOldDicionarioMER + " since its nomeProjeto field is not nullable.");
                }
            }
            
            if( dicionarioMRListNew !=null)
            for (DicionarioMR dicionarioMRListOldDicionarioMR : dicionarioMRListOld) {
                if (!dicionarioMRListNew.contains(dicionarioMRListOldDicionarioMR)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain DicionarioMR " + dicionarioMRListOldDicionarioMR + " since its nomeProjeto field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            List<Projetista> attachedProjetistaListNew = new ArrayList<Projetista>();
            
            if( projetistaListNew !=null)
            for (Projetista projetistaListNewProjetistaToAttach : projetistaListNew) {
                projetistaListNewProjetistaToAttach = em.getReference(projetistaListNewProjetistaToAttach.getClass(), projetistaListNewProjetistaToAttach.getEMail());
                attachedProjetistaListNew.add(projetistaListNewProjetistaToAttach);
            }
            projetistaListNew = attachedProjetistaListNew;
            esquema.setProjetistaList(projetistaListNew);
            List<DicionarioMER> attachedDicionarioMERListNew = new ArrayList<DicionarioMER>();
            
            if( dicionarioMERListNew !=null)
            for (DicionarioMER dicionarioMERListNewDicionarioMERToAttach : dicionarioMERListNew) {
                dicionarioMERListNewDicionarioMERToAttach = em.getReference(dicionarioMERListNewDicionarioMERToAttach.getClass(), dicionarioMERListNewDicionarioMERToAttach.getId());
                attachedDicionarioMERListNew.add(dicionarioMERListNewDicionarioMERToAttach);
            }
            dicionarioMERListNew = attachedDicionarioMERListNew;
            esquema.setDicionarioMERList(dicionarioMERListNew);
            List<DicionarioMR> attachedDicionarioMRListNew = new ArrayList<DicionarioMR>();
            
            if( dicionarioMRListNew !=null)
            for (DicionarioMR dicionarioMRListNewDicionarioMRToAttach : dicionarioMRListNew) {
                dicionarioMRListNewDicionarioMRToAttach = em.getReference(dicionarioMRListNewDicionarioMRToAttach.getClass(), dicionarioMRListNewDicionarioMRToAttach.getId());
                attachedDicionarioMRListNew.add(dicionarioMRListNewDicionarioMRToAttach);
            }
            dicionarioMRListNew = attachedDicionarioMRListNew;
            esquema.setDicionarioMRList(dicionarioMRListNew);
            esquema = em.merge(esquema);
            
            if( projetistaListNew !=null)
            for (Projetista projetistaListOldProjetista : projetistaListOld) {
                if (!projetistaListNew.contains(projetistaListOldProjetista)) {
                    projetistaListOldProjetista.getEsquemaList().remove(esquema);
                    projetistaListOldProjetista = em.merge(projetistaListOldProjetista);
                }
            }
            
            if( projetistaListNew !=null)
            for (Projetista projetistaListNewProjetista : projetistaListNew) {
                if (!projetistaListOld.contains(projetistaListNewProjetista)) {
                    projetistaListNewProjetista.getEsquemaList().add(esquema);
                    projetistaListNewProjetista = em.merge(projetistaListNewProjetista);
                }
            }
            
            if( dicionarioMERListNew !=null)
            for (DicionarioMER dicionarioMERListNewDicionarioMER : dicionarioMERListNew) {
                if (!dicionarioMERListOld.contains(dicionarioMERListNewDicionarioMER)) {
                    Esquema oldNomeProjetoOfDicionarioMERListNewDicionarioMER = dicionarioMERListNewDicionarioMER.getNomeEsquema();
                    dicionarioMERListNewDicionarioMER.setNomeEsquema(esquema);
                    dicionarioMERListNewDicionarioMER = em.merge(dicionarioMERListNewDicionarioMER);
                    if (oldNomeProjetoOfDicionarioMERListNewDicionarioMER != null && !oldNomeProjetoOfDicionarioMERListNewDicionarioMER.equals(esquema)) {
                        oldNomeProjetoOfDicionarioMERListNewDicionarioMER.getDicionarioMERList().remove(dicionarioMERListNewDicionarioMER);
                        oldNomeProjetoOfDicionarioMERListNewDicionarioMER = em.merge(oldNomeProjetoOfDicionarioMERListNewDicionarioMER);
                    }
                }
            }
            
            if( dicionarioMRListNew !=null)
            for (DicionarioMR dicionarioMRListNewDicionarioMR : dicionarioMRListNew) {
                if (!dicionarioMRListOld.contains(dicionarioMRListNewDicionarioMR)) {
                    Esquema oldNomeProjetoOfDicionarioMRListNewDicionarioMR = dicionarioMRListNewDicionarioMR.getNomeEsquema();
                    dicionarioMRListNewDicionarioMR.setNomeEsquema(esquema);
                    dicionarioMRListNewDicionarioMR = em.merge(dicionarioMRListNewDicionarioMR);
                    if (oldNomeProjetoOfDicionarioMRListNewDicionarioMR != null && !oldNomeProjetoOfDicionarioMRListNewDicionarioMR.equals(esquema)) {
                        oldNomeProjetoOfDicionarioMRListNewDicionarioMR.getDicionarioMRList().remove(dicionarioMRListNewDicionarioMR);
                        oldNomeProjetoOfDicionarioMRListNewDicionarioMR = em.merge(oldNomeProjetoOfDicionarioMRListNewDicionarioMR);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = esquema.getNome();
                if (findEsquema(id) == null) {
                    throw new NonexistentEntityException("The esquema with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Esquema esquema;
            try {
                esquema = em.getReference(Esquema.class, id);
                esquema.getNome();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The esquema with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<DicionarioMER> dicionarioMERListOrphanCheck = esquema.getDicionarioMERList();
            for (DicionarioMER dicionarioMERListOrphanCheckDicionarioMER : dicionarioMERListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Esquema (" + esquema + ") cannot be destroyed since the DicionarioMER " + dicionarioMERListOrphanCheckDicionarioMER + " in its dicionarioMERList field has a non-nullable nomeProjeto field.");
            }
            List<DicionarioMR> dicionarioMRListOrphanCheck = esquema.getDicionarioMRList();
            for (DicionarioMR dicionarioMRListOrphanCheckDicionarioMR : dicionarioMRListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Esquema (" + esquema + ") cannot be destroyed since the DicionarioMR " + dicionarioMRListOrphanCheckDicionarioMR + " in its dicionarioMRList field has a non-nullable nomeProjeto field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            List<Projetista> projetistaList = esquema.getProjetistaList();
            for (Projetista projetistaListProjetista : projetistaList) {
                projetistaListProjetista.getEsquemaList().remove(esquema);
                projetistaListProjetista = em.merge(projetistaListProjetista);
            }
            em.remove(esquema);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Esquema> findEsquemaEntities() {
        return findEsquemaEntities(true, -1, -1);
    }

    public List<Esquema> findEsquemaEntities(int maxResults, int firstResult) {
        return findEsquemaEntities(false, maxResults, firstResult);
    }

    private List<Esquema> findEsquemaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Esquema.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Esquema findEsquema(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Esquema.class, id);
        } finally {
            em.close();
        }
    }

    public int getEsquemaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Esquema> rt = cq.from(Esquema.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
